package com.alibaba.algo.apiimpl.user;

import com.alibaba.algo.cooperation.common.BaseResult;
import com.alibaba.algo.cooperation.usercomponent.service.user.SysOrgLabelService;
import com.alibaba.algo.cooperation.usercomponent.vo.req.user.OrgLabelEmployeeRelation;
import com.alibaba.algo.cooperation.usercomponent.vo.req.user.OrgLabelEmployeeRequestVO;
import com.alibaba.algo.cooperation.usercomponent.vo.req.user.OrgLabelPageVO;
import com.alibaba.algo.cooperation.usercomponent.vo.res.user.SysLabelEmployeeInfo;
import com.alibaba.algo.cooperation.usercomponent.vo.res.user.SysLabelOrgEmployeeInfo;
import com.alibaba.algo.cooperation.usercomponent.vo.res.user.SysOrgLabelDetailVO;
import com.alibaba.algo.core.base.Pager;
import com.alibaba.algo.core.base.PagerEntity;
import com.alibaba.algo.domain.user.SysLabelDomain;
import com.alibaba.algo.domain.user.SysLabelOrgDomain;
import com.alibaba.algo.domain.user.SysLabelOrgEmployeeDomain;
import com.alibaba.algo.entity.user.*;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 岗位标签相关接口实现类
 *
 * @author Songtinghua
 * @create 2021-10-29 11:03
 **/
@Slf4j
@RestController
public class SysOrgLabelServiceImpl implements SysOrgLabelService {

    @Autowired
    SysLabelDomain sysLabelDomain;

    @Autowired
    SysLabelOrgDomain sysLabelOrgDomain;

    @Autowired
    SysLabelOrgEmployeeDomain sysLabelOrgEmployeeDomain;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public BaseResult insert(@RequestBody OrgLabelEmployeeRequestVO param) {

        Integer count = sysLabelDomain.selectCountByLabelCode(param.getLabelCode());
        if (count > 0) {
            return BaseResult.buildError("岗位标签已存在！");
        }
        if (checkHasOrNotSameOrg(param.getOrgEmployeeRelations())) {
            return BaseResult.buildError("关系组织存在重复项！");
        }
        if (checkHasOrNotSameEmployee(param.getOrgEmployeeRelations())) {
            return BaseResult.buildError("同组织下存在相同的员工！");
        }
        //保持标签信息
        SysLabel sysLabel = new SysLabel();
        sysLabel.setLabelName(param.getLabelName());
        sysLabel.setLabelCode(param.getLabelCode());
        if (!StringUtils.isEmpty(param.getLabelDesc())) {
            sysLabel.setLabelDesc(param.getLabelDesc());
        }
        if (!StringUtils.isEmpty(param.getStatus())) {
            sysLabel.setStatus(param.getStatus());
        }
        sysLabel.setCreator(param.getUserName());
        sysLabel.setModifier(param.getUserName());
        LocalDateTime now = LocalDateTime.now();
        sysLabel.setGmtCreated(now);
        sysLabel.setGmtModified(now);
        sysLabelDomain.insert(sysLabel);
        //保存与标签相关联的组织和员工信息
        saveEmployeeAndOrgInfo(param);
        return BaseResult.buildSuccess();
    }

    /**
     * 保存对应标签下的员工信息
     *
     * @param param web input param
     */
    private void saveEmployeeAndOrgInfo(OrgLabelEmployeeRequestVO param) {
        LocalDateTime now = LocalDateTime.now();
        List<OrgLabelEmployeeRelation> orgEmployeeRelations = param.getOrgEmployeeRelations();
        if (!CollectionUtils.isEmpty(orgEmployeeRelations)) {
            SysLabel label = sysLabelDomain.selectByLabelCode(param.getLabelCode());
            orgEmployeeRelations.forEach(item -> {
                SysLabelOrg sysLabelOrg = new SysLabelOrg();
                sysLabelOrg.setSysLabelId(label.getId());
                sysLabelOrg.setSysOrgId(item.getSysOrgId());
                sysLabelOrg.setCreator(param.getUserName());
                sysLabelOrg.setModifier(param.getUserName());
                sysLabelOrg.setGmtCreated(now);
                sysLabelOrg.setGmtModified(now);
                sysLabelOrgDomain.insert(sysLabelOrg);
                if (!CollectionUtils.isEmpty(item.getSysEmployeeIds())) {
                    SysLabelOrg labelOrg = sysLabelOrgDomain.selectByLabelIdAndOrgId(label.getId(), item.getSysOrgId());
                    item.getSysEmployeeIds().forEach(employeeId -> {
                        SysLabelOrgEmployee labelOrgEmployee = new SysLabelOrgEmployee();
                        labelOrgEmployee.setSysLabelOrgId(labelOrg.getId());
                        labelOrgEmployee.setSysEmployeeId(employeeId);
                        labelOrgEmployee.setCreator(param.getUserName());
                        labelOrgEmployee.setModifier(param.getUserName());
                        labelOrgEmployee.setGmtCreated(now);
                        labelOrgEmployee.setGmtModified(now);
                        sysLabelOrgEmployeeDomain.insert(labelOrgEmployee);
                    });
                }
            });
        }
    }

    /**
     * 校验是否存在相同的组织
     *
     * @param orgEmployeeRelations web input param
     * @return boolean
     */
    private Boolean checkHasOrNotSameOrg(List<OrgLabelEmployeeRelation> orgEmployeeRelations) {
        if (!CollectionUtils.isEmpty(orgEmployeeRelations)) {
            long distinctCount = orgEmployeeRelations.stream().map(OrgLabelEmployeeRelation::getSysOrgId).distinct().count();
            return orgEmployeeRelations.size() != distinctCount;
        }
        return false;
    }

    /**
     * 校验同一种组织下是否存在相同的员工
     *
     * @param orgEmployeeRelations web input param
     * @return boolean
     */
    private Boolean checkHasOrNotSameEmployee(List<OrgLabelEmployeeRelation> orgEmployeeRelations) {
        if (!CollectionUtils.isEmpty(orgEmployeeRelations)) {
            for (OrgLabelEmployeeRelation orgLabelEmployeeRelation : orgEmployeeRelations) {
                List<Long> employeeIds = orgLabelEmployeeRelation.getSysEmployeeIds();
                if (!CollectionUtils.isEmpty(employeeIds)) {
                    long distinctCount = employeeIds.stream().distinct().count();
                    return employeeIds.size() != distinctCount;
                }
            }
        }
        return false;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public BaseResult update(@RequestBody OrgLabelEmployeeRequestVO param) {

        SysLabel sysLabel = sysLabelDomain.getById(param.getId());
        if (null == sysLabel) {
            return BaseResult.buildError("当前数据已不存在，请刷新！");
        }
        if (!StringUtils.isEmpty(param.getLabelCode()) && !param.getLabelCode().equals(sysLabel.getLabelCode())) {
            return BaseResult.buildError("便签编码不可修改!");
        }
        List<OrgLabelEmployeeRelation> orgEmployeeRelations = param.getOrgEmployeeRelations();
        if (checkHasOrNotSameOrg(orgEmployeeRelations)) {
            return BaseResult.buildError("关系组织存在重复项！");
        }
        if (checkHasOrNotSameEmployee(orgEmployeeRelations)) {
            return BaseResult.buildError("同组织下存在相同的员工！");
        }
        //更新标签信息
        BeanUtils.copyProperties(param, sysLabel, "id");
        sysLabel.setModifier(param.getUserName());
        LocalDateTime now = LocalDateTime.now();
        sysLabel.setGmtModified(now);
        sysLabelDomain.updateById(sysLabel);
        //详情更新(状态更新时，前端直传status字段信息；详情更新时，传全部数据)
        if (null != param.getOrgEmployeeRelations()) {
            //删除标签下相关联的组织和员工信息
            deleteEmployeeAndOrgInfo(param.getId());
            //新增标签下相关联的组织和员工信息
            saveEmployeeAndOrgInfo(param);
        }
        return BaseResult.buildSuccess();
    }

    /**
     * 删除对应标签下的员工和组织信息
     *
     * @param sysLabelId label id
     */
    private void deleteEmployeeAndOrgInfo(Long sysLabelId) {
        //删除标签下对应的组织和员工信息
        List<SysLabelOrg> sysLabelOrgs = sysLabelOrgDomain.selectByLabelId(sysLabelId);
        if (!CollectionUtils.isEmpty(sysLabelOrgs)) {
            sysLabelOrgs.forEach(item -> sysLabelOrgEmployeeDomain.updateBySysLabelOrgId(item.getId()));
            sysLabelOrgDomain.updateBySysLabelId(sysLabelId);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public BaseResult delete(@RequestBody List<Long> ids) {
        ids.forEach(id -> {
            //删除标签信息
            SysLabel sysLabel = new SysLabel();
            sysLabel.setId(id);
            sysLabel.setIsDeleted("Y");
            sysLabelDomain.updateById(sysLabel);
            //删除标签下对应的组织和员工信息
            deleteEmployeeAndOrgInfo(id);
        });
        return BaseResult.buildSuccess();
    }

    @Override
    public BaseResult selectDetail(@RequestParam("id") Long id) {
        SysOrgLabelDetailVO sysOrgLabelDetailVO = null;
        List<SysOrgLabelDetail> sysOrgLabelDetails = sysLabelDomain.selectDetailById(id);
        if (!CollectionUtils.isEmpty(sysOrgLabelDetails)) {
            sysOrgLabelDetailVO = new SysOrgLabelDetailVO();
            sysOrgLabelDetailVO.setId(sysOrgLabelDetails.get(0).getId());
            sysOrgLabelDetailVO.setLabelName(sysOrgLabelDetails.get(0).getLabelName());
            sysOrgLabelDetailVO.setLabelCode(sysOrgLabelDetails.get(0).getLabelCode());
            sysOrgLabelDetailVO.setLabelDesc(sysOrgLabelDetails.get(0).getLabelDesc());
            sysOrgLabelDetailVO.setStatus(sysOrgLabelDetails.get(0).getStatus());
            List<SysLabelOrgEmployeeInfo> orgEmployeeInfos = Lists.newArrayList();
            List<Long> orgIds = sysOrgLabelDetails.stream().map(SysOrgLabelDetail::getSysOrgId).distinct().collect(Collectors.toList());
            orgIds.forEach(orgId -> {
                if (null == orgId) {
                    return;
                }
                SysLabelOrgEmployeeInfo orgEmployeeInfo = new SysLabelOrgEmployeeInfo();
                List<SysLabelEmployeeInfo> employeeInfos = Lists.newArrayList();
                orgEmployeeInfo.setSysOrgId(orgId);
                SysOrgLabelDetail sysOrgLabelDetail = sysOrgLabelDetails.stream().filter(a -> a.getSysOrgId().equals(orgId)).findFirst().get();
                orgEmployeeInfo.setOrgName(sysOrgLabelDetail.getOrgName());
                sysOrgLabelDetails.forEach(item -> {
                    if (item.getSysOrgId().equals(orgId)) {
                        SysLabelEmployeeInfo employeeInfo = new SysLabelEmployeeInfo();
                        employeeInfo.setSysEmployeeId(item.getSysEmployeeId());
                        employeeInfo.setEmployeeName(item.getEmployeeName());
                        employeeInfos.add(employeeInfo);
                    }
                    orgEmployeeInfo.setEmployeeInfo(employeeInfos);
                });
                orgEmployeeInfos.add(orgEmployeeInfo);
            });
            sysOrgLabelDetailVO.setOrgEmployeeInfo(orgEmployeeInfos);
        }

        return BaseResult.buildSuccess(sysOrgLabelDetailVO);
    }

    @Override
    public BaseResult selectPage(@RequestBody OrgLabelPageVO param) {
        if (null == param) {
            param = new OrgLabelPageVO();
        }
        if (null == param.getPageIndex()) {
            param.setPageIndex(1);
        }
        if (null == param.getPageSize()) {
            param.setPageSize(10);
        }
        List<SysOrgLabelList> sysOrgLabelLists = sysLabelDomain.selectByPage(param);
        PagerEntity<SysOrgLabelList> pagerEntity;
        if (!CollectionUtils.isEmpty(sysOrgLabelLists)) {
            Integer count = sysLabelDomain.count(param);
            Pager pager = Pager.newInstance(Long.parseLong(count.toString()), param.getPageIndex(), param.getPageSize());
            pagerEntity = new PagerEntity<>(count, pager.getTotalPages(), param.getPageIndex(), param.getPageSize(), sysOrgLabelLists);
        } else {
            Pager pager = Pager.newInstance(0L, param.getPageIndex(), param.getPageSize());
            pagerEntity = new PagerEntity<>(0, pager.getTotalPages(), param.getPageIndex(), param.getPageSize(), null);
        }
        return BaseResult.buildSuccess(pagerEntity);
    }
}
